package com.heima.search.service.impl;

import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.dtos.UserSearchDto;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;

@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Autowired
    RestHighLevelClient client;
    @Autowired
    ApUserSearchService apUserSearchService;
    @Value("${elasticsearch.index_Date}")
    private String index;
    /**
     * ES文章分页搜索
     *
     * @param userSearchDto
     * @return
     */
    @Override
    public ResponseResult search(UserSearchDto userSearchDto) {
        //1.参数校验
        if (userSearchDto==null|| StringUtils.isBlank(userSearchDto.getSearchWords())){
            return ResponseResult.okResult();
        }
        //最小时间
        if (userSearchDto.getMinBehotTime()==null){
            userSearchDto.setMinBehotTime(new Date());
        }
        if (userSearchDto.getPageSize()>50||userSearchDto.getPageSize()<=0){
            userSearchDto.setPageSize(10);
        }
        //*****异步记录搜索关键词
        ApUser user = AppThreadLocalUtils.getUser();
        if (user!=null&&user.getId()!=0){
            log.info("***********开始异步保存搜索记录");
            apUserSearchService.insert(userSearchDto.getSearchWords(),user.getId());
        }

        //2.查询条件 bool查询
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

        //关键字
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", userSearchDto.getSearchWords());
        queryBuilder.must(matchQueryBuilder);

        //过滤条件  发布时间小于当前页最后一条记录的发布时间
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(userSearchDto.getMinBehotTime());
        queryBuilder.filter(rangeQueryBuilder);

        //排序
        searchSourceBuilder.sort("publishTime", SortOrder.DESC);

        //分页
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(userSearchDto.getPageSize());
        //高亮三要素
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title"); //高亮字段
        highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");//前缀
        highlightBuilder.postTags("</font>");//后缀
        searchSourceBuilder.highlighter(highlightBuilder);
        //3.查询

        searchSourceBuilder.query(queryBuilder);
        SearchRequest request=new SearchRequest(index);
        request.source(searchSourceBuilder);
        ArrayList<Map> result = new ArrayList<>();
        try {
            SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);
            //4.解析结果
            SearchHits hits = searchResponse.getHits();
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit searchHit : searchHits) {
                //结果
                Map<String, Object> map = searchHit.getSourceAsMap();
                //高亮
                HighlightField highlightField = searchHit.getHighlightFields().get("title");
                if (highlightField!=null&&highlightField.getFragments().length>0){
                    Text[] fragments = highlightField.getFragments();
                    String title = StringUtils.join(fragments);
                    map.put("h_title",title);
                }else {
                    map.put("h_title",map.get("title"));
                }
                result.add(map);
            }
            //5.返回结果
            return ResponseResult.okResult(result);
        } catch (IOException e) {
            log.error("search error Exception:"+e);
        }


        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
    }
}
